/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
 * Description: 
 * Author: g00421808
 * Create: 6/28/2022
 * Notes: 
 */

#ifndef JSBIND_NAPI_SETTER_BINDER_H
#define JSBIND_NAPI_SETTER_BINDER_H
#include "jsbind/binder/setter_binder.h"

namespace Jsb {

template <typename C, typename M, typename R, typename P>
class NapiSetterBinder : public SetterBinder<NapiSetterBinder<C, M, R, P>, C, M, R, P> {
public:
    typedef SetterBinder<NapiSetterBinder<C, M, R, P>, C, M, R, P> ParentType;

    static napi_value Wrapper (napi_env env, napi_callback_info info) {
        JSB_DLOG(DEBUG) << "NapiSetterBinder::Wrapper";
        return SafetyWrapper(env, info);
    }

private:
    static napi_value SafetyWrapper(napi_env& env, napi_callback_info info) {
        napi_status status;
        Jsb::BindInfo* bindInfo = nullptr;
        napi_value jsThis;
        size_t argc = 1; /// 默认set访问器只有一个入参
        napi_value args[1];
        status = napi_get_cb_info(env, info, &argc, args, &jsThis, ((void**)&bindInfo));
        JSB_DCHECK(status == napi_ok);
        JSB_DCHECK(bindInfo != nullptr);

        /// 获取ClassType对象实例
        C* receiver = ClassWrapper<C>::UnWrapper(env, jsThis);

        auto tuple = std::make_tuple(NapiValueMaker<typename ValueDefiner<P>::RawType>(env, args[0]));
        auto valueTuple = std::make_tuple(NapiValueTrait<typename ValueDefiner<P>::RawType>::Cast(std::get<0>(tuple)));
        return WrapperForward(env, bindInfo, receiver, std::get<0>(valueTuple));
    }

    template<typename ArgType>
    static napi_value WrapperForward(napi_env& env, Jsb::BindInfo* bindInfo, C* receiver, ArgType&& arg) {
        ParentType::InnerWrapper(*receiver, bindInfo, std::forward<ArgType>(arg));
        return nullptr;
    }
};
} // namespace Jsb
#endif //JSBIND_NAPI_SETTER_BINDER_H
